//  Copyright 2004 The Apache Software Foundation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package org.redswallow.util.config;

import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.MissingResourceException;
import java.util.ResourceBundle;

import org.redswallow.log.LogFactory;
import org.redswallow.util.Utils;
import org.slf4j.Logger;


/**
 *  An implementation of {@link IPropertySource}
 *  that delegates to a list of other implementations.  This makes
 *  it possible to create a search path for property values.
 *
 *  @author Howard Lewis Ship
 *  @version $Id: DelegatingPropertySource.java 243791 2004-02-19 17:38:13Z hlship $
 *  @since 2.3
 *
 **/

public class DelegatingPropertySet extends AbstractPropertySet {
    
	private List<IPropertySet> _sources = new ArrayList<IPropertySet>();
    
	private Logger log = LogFactory.getLog(DelegatingPropertySet.class);
	
    public DelegatingPropertySet()
    {
    }
    
    public DelegatingPropertySet(IPropertySet delegate)
    {
        addSource(delegate);
    }
    
    /**
     *  Adds another source to the list of delegate property sources.
     *  This is typically only done during initialization
     *  of this DelegatingPropertySource.
     * 
     **/
    
    public void addSource(IPropertySet source)
    {
    	addSource(source, true);
    }
    
    public void addSource(IPropertySet source, boolean autoImports) {
    	
    	_sources.add(source);
    	
    	//auto load imports
    	if (autoImports) {
    		
    		String imports = source.getString(ConfigConstants.REDSWALLOW_IMPORTS, null);
    		
    		if (Utils.isBlank(imports)) return;
    		
    		String[] sl = (";"+imports+";").split("\\s*;\\s*");
    		
    		Locale currentLocale = Locale.getDefault();
    		ClassLoader cl = Thread.currentThread().getContextClassLoader();
    		if (cl == null) {
    		    cl = ClassLoader.getSystemClassLoader();
    		}
    		
    		for(int i=0; i < sl.length; ++i) {
    			
    			if (Utils.isBlank(sl[i])) continue;
    			
    			ResourceBundle bundle = null;
    			
    			
    			try{
    				bundle = ResourceBundle.getBundle(sl[i], currentLocale, cl);
    			}catch(MissingResourceException e) {
    				log.error("source not found.", e);
    				log.debug("property file '{}' not found.", ConfigConstants.CUSTOM_XSS_CHECKER_PROPERTY);
    			}catch(Exception e) {
    				log.error("getBundle exception.", e);
    				log.debug("bundle property file '{}' exception.", ConfigConstants.CUSTOM_XSS_CHECKER_PROPERTY);
    			}
    			
    			if (bundle != null)
    				addSource(new ResourceBundlePropertySet(bundle), true);
    		}
    		
    	}
    }
    
    /**
     *  Re-invokes the method on each delegate property source, 
     *  in order, return the first non-null value found.
     * @throws Exception 
     * 
     **/
    
    protected String getProperty(String propertyName) throws Exception
    {
        String result = null;
        int count = _sources.size();
        
        for (int i = count; i > 0; --i)
        {
        	IPropertySet source = (IPropertySet)_sources.get(i-1);
            
            result = source.getString(propertyName, null);
            
            if (result != null)
                break;
        }
        
        if (result==null)
        	throw new Exception("no property.");
        
        return result;        
    }

}
